PICの応用回路(2) ・・・・ データロガー(その1)、電圧計: ADコンバーター、液晶表示器
1. データロガーの作製:
データロガーは、各種のセンサから電圧信号を受け取り、演算を加え、データを
LCDで表示したり、CSV形式でパソコンへ送って処理しやすくする働きをする。 その入力側の基本形は、ADコンバーターを通しての 電圧計(0−5Vなど(電源電圧)を(8ビットでは)1024分割する)であり、これに 各種のセンサからの電圧信号を処理する機能を付け加えると、非常に応用範囲の広いシステムが出来上がる。
出力側は、常時 結果を表示する 液晶表示器(LCD)や7セグLEDと共に、必要に応じて、パソコンにデータを送るための
シリアル通信やUSB通信の機能を持たせる形となる。
(1) 液晶表示2チャンネル電圧計の作製:
@ PICの選定と接続回路図:
PIC16F877Aは、ADコンバーターとシリアル機能の両方を有し(cf. PIC12F675はシリアル無し、PIC16F628AはADコンバーター無し)、ピン数が多く(40pin)かさばる上、クロック生成器が不完全で水晶を必要とするが、汎用ポートが5組もあり、LCDのように多くのメモリを必要とするデータロガーにはふさわしいと思われる。(* ただし、シリアル通信は、シリアル出力端が無くてもプログラムで作ることができる。
温度計などの 機能が特化された専用器には、もっとコンパクトなPICを用いる。)
PIC12F675 | PIC16F628A | PIC16F877A | |
フラッシュメモリ(プログラムの保存) | 1kワード | 2kワード | 8kワード |
RAM(変数・バッファの割り当て) | 64バイト | 224バイト | 368バイト |
クロック生成器 | 内蔵 | 内蔵 | 不完全 |
タイマ0(標準8ビットタイマ) | 内蔵 | 内蔵 | 内蔵 |
タイマ1(16ビットタイマ) | 内蔵 | 内蔵 | 内蔵 |
タイマ2(周期設定可8ビット) | なし | 内蔵 | 内蔵 |
CCPモジュール | なし | 内蔵 | 内蔵 |
汎用ポート | 1組6本 | 2組16本 | 5組33本 |
コンパレータ | 1基 | 2基 | 1基 |
ADコンバータ | 4チャンネル | なし | 8チャンネル |
シリアル | なし | 内蔵 | 内蔵 |
同期式シリアル(SPI、I2C) | なし | なし | 内蔵 |
PSP(ローカルバス送受信) | なし | なし | 内蔵 |
PIC16F877Aの ポートAをアナログ入力、ポートBをLCD駆動、ポートCをシリアル通信に割り当てた。(ポートD、Eは不使用) アナログ入力は AN0、AN1の2本(2チャンネルとなる)、LCD駆動は DB4〜7の4ビット・ドライブ、シリアルは TX(送信)、RX(受信)の2本だけとなる。 (* 配線は複雑そうに見えるが、ピンさえ間違えなければ比較的簡単にできる。
プリント基板(ナマ基板)へのICピッチの穴あけは、ユニバーサル基板を重ねてその上からφ.8ドリルで行なうと
それほどずれない)
A AD変換 と 簡単な演算:
AD変換は、main関数の 各チャンネルごとに行なわれる。 チャンネル0では、ADCON0 の設定は、10000001 : 上位桁から 右寄せ、電源電圧、−、−、チャンネル0、チャンネル0、変換終了、電源スイッチON、のようになる。チャンネル1では、10001001 となる。
* (追記) AD変換後のデータを取り出す記述を、 v=(ADRESH<<8)|ADRESL; から v=(ADRESH*256)+ADRESL; に変更します。前者は、PICのシフトレジスタの設計が悪くデータ取得ができないか不安定で、数値がふらつく原因となっている。
ADコンバータの値は、電源電圧 5Vを 1024分割した値刻みの 0−1023 なので、5桁の作業領域を取ると、50000/1024 ≒ 49 をその値に掛けた数値、すなわち、変換結果 × 49 を計算し、小数点を2番目に入れ、○.○○○V の表示とする。(* 掛け算の最大値は、1023×49=50127 で、2バイトの変数領域 65535
以下なので、オーバーフロしない)
小数点付きの計算はメモリを食うので、極力 整数型で計算する。
B 液晶表示器の初期設定:
LCDは、多くの場合、起動時、転送単位が 8ビット・モードになっているので、4ビットしか接続していない上記の回路では、4ビット・モードに設定し直す必要がある。
LCDの ファンクションセットは、0,0,1,DL,N,F,0,0 で、 DL:転送単位(1: 8ビット、0: 4ビット)、N:表示行数(1: 2行、0: 1行)、F: フォントのドット構成(1: 5×10、0: 5×7) より、 0x03 = 0011 xxxx = 転送単位 8ビット、 0x28 = 0010 1000 = (4ビット、2行、5×7ドット) となる。
OPTION で、プリスケーラーを 1/256 に設定(・ PIC16F628Aでは クロック4MHzなので 1/64)して、ファンクションセット時のそれぞれの必要な時間をつぶす。(20MHzの水晶発振子用であるが、10MHzにしても問題ない。)
このように、LCDの起動時の不確定な動作を、3度も設定命令を出して確実に8ビットにしてから、改めて4ビットに切り替える必要がある。
C 液晶表示プログラム:
AD変換や演算によって与えられた数値データを、文字データに変換して 液晶やシリアル通信に送る必要がある。このための関数群(API)にまとめておくと便利である。
液晶表示のAPIの一例として、
下図の左側は、8ビットのデータを 上位4ビット・下位4ビットに分けて
LCDに送るための基本関数群で、ビジー・フラグ(LCDからの唯一の入力)を確認して
同期信号を出し 書き込み可能になるのを待って命令とデータを書き込む。(* 随所に挿入されている
NOP( ) はLCDが遅いことによる時間調整のためで、発振周波数4MHz以下では不要)
右側は、main関数で用いられる出力用関数群で、
・ lcd_locate(x, y) : LCDの書き込み位置(カーソルの位置) ・・・・ ex) lcd_locate(0,
1) : 2行目の先頭、 lcd_locate(7, 1) : 2行目の8番目
・ lcd_putchr(d) : 1文字d(8ビット)を書き込む ・・・ lcd_putchr('d')
: 1文字だけ
・ lcd_puts(*s) : 文字列を書き込む ・・・ lcd_puts("abcde
fgh") : 何文字でも良い(C言語文字列の最後は0)
・ lcd_putv(v) : 数値データを 文字列(4桁、小数点付き)に変換して書き込む
また、次の ・ lcd_putui (ui, d) ・・・ 数値 ui をd桁の10進数で表示、 ・ lcd_puthc(d)
・・・ 16進数で表示、 ・ lcd_lclr( l ) ・・・ 指定行ごとに全クリヤ(LCD表示器は40文字×2行)、 も有用な関数で、そのまま、あるいは、小数点やブランクなどの一部の変更で用いることができる。
● ソース: